package autorization;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ConcurrentHashMap;


/**
 * Класс таблицы правил политики безопасности для системы ролей проекта
 * @author Volk ID = 1001
 * @version = 0.1 Базовый функционал тестового модуля
 */
public class RulesTable implements IRulesTable {
    //--------------------------Inner attributes--------------------------
    private static volatile int counterID = 0; //Счетчик для выдачи уникальных идентификаторов правил
    //Таблица для преобразования имени в идентифкатор
    private ConcurrentHashMap<String,LongComparable> mapID = new ConcurrentHashMap<String,LongComparable>();
    //Таблица для преобразования идентификатор в значение
    private ConcurrentHashMap<LongComparable,Rule> map = new ConcurrentHashMap<LongComparable,Rule>();
    private volatile int size = 0; //размерность таблицы
    //--------------------------------------------------------------------
    /**
     * Конструктор по умолчанию
     */
    public RulesTable () {}

    //---------------Перегрузка методов добавления записи-----------
    /**
     * Добавить правило в таблицу
     * @param rule - класс правила
     * @return -1 в случае если правило с таким именем уже зарегистрировано, в случае успеха возвращает ID правила
     */
    public long addRule (Rule rule) {
       if(mapID.containsKey(rule.getName())) return -1; //Зарегистрировано ли правило с таким именем?
       LongComparable lg = new LongComparable(counterID);
       
       mapID.putIfAbsent(rule.getName(), lg); //Добавление правила по таблицам преобразования
       map.putIfAbsent(lg, rule);
       
       long result = counterID++; // Формирование идентификатора правила

       size++;
       return result;
    }
     /**
     * Добавить правило в таблицу
     * @param name - УНИКАЛЬНОЕ имя правила
     * @param type - тип правила
     * @param tooltip - текстовая подсказка, поясняющая суть правила
     * @return -1 в случае если правило с таким именем уже зарегистрировано, в случае успеха возвращает ID правила
     */
    public long addRule (String name, int type, String tooltip) {
        Rule rule = new Rule(name, type, tooltip);
        return addRule(rule);
    }

    //---------------------------------------------------------------

    //---------------Перегрузка методов удаления записи--------------
    /**
     * Удаление правила из таблицы
     * @param ID - идентификатор правила
     * @return true - удаление прошло успешно, false - отказ в удалении в силу того что правило с указанным идентификаторо не зарегистрировано в таблице
     */
    public boolean deleteRule (long ID) {
        LongComparable lg = new LongComparable(ID);
        if(!map.containsKey(lg)) return false; //Зарегистрировано ли правило с таким именем?
        Rule rule = map.get(lg); //Получить правило по идентфикатору
        
        map.remove(lg);  //удаление информации о правиле из таблиц
        mapID.remove(rule.getName());

        size--;
        return true;
    }

    /**
     * Удаление правила из таблицы
     * @param name - уникальное имя правила
     * @return - удаление прошло успешно, false - отказ в удалении в силу того что правило с указанным именем не зарегистрировано в таблице
     */
    public boolean deleteRule (String name) {
      LongComparable lg = mapID.get(name);
      if(lg == null) return false;
      return deleteRule(lg.value);
    }

    //---------------------------------------------------------------
    /**
     * Получить идентификатор правила по имени
     * @param name - имя правила
     * @return в случае успеха идентификатор правила, но в случае если правило с таким именем не зарегистрировано в таблице возвращает -1
     */
    public long getID (String name) {
      LongComparable lg = mapID.get(name);
      if(lg == null) return -1;
       else return lg.value;
    }

    //--------------Перегрузка методов проверки наличия правила в таблице------
    /**
     * Проверяет наличие правила в таблице
     * @param name - уникальное умя правила
     * @return true - правило присутствует в таблице, false - правила нет в таблице
     */
    public boolean isRule (String name) {
      return mapID.containsKey(name);
    }

    /**
     * Проверяет наличие правила в таблице
     * @param ID - уникальный идентификато правила
     * @return true - правило присутствует в таблице, false - правила нет в таблице
     */
    public boolean isRule (long ID) {
      LongComparable lg = new LongComparable(ID);
      boolean result = map.containsKey(lg);
      return result;
    }

    //-------------------------------------------------------------------------

    /**
     * Удалить все записи из таблицы
    */
    public void clear () {
      map.clear();
      mapID.clear();
      size = 0;
    }


   //----------------Перегрузка методов получения правила из таблицы------
    /**
     * Получить правило из таблицы
     * @param ID - идентификатор правила
     * @return правило в случае успеха, null в случае если правила с таким именем нет в таблице
     */
    public Rule getRule (long ID) {
        LongComparable lg = new LongComparable(ID);
        return map.get(lg);
    }

     /**
     * Получить правило из таблицы
     * @param name - имя правила
     * @return правило в случае успеха, null в случае если правила с таким именем нет в таблице
     */
    public Rule getRule (String name) {
      LongComparable lg = mapID.get(name);
      if(lg == null) return null;
      return getRule(lg.value);
    }

     //---------------------------------------------------------------------

    /**
     * Модифицировать правила в таблице
     * @param rule - модифицированный объект правила
     * @return true - правило изменено, false - правило в заданными параметрами нет в таблице
     */
    public boolean modifyRule (Rule rule) {
        LongComparable lg = mapID.get(rule.getName());
        if(lg == null) return false;
        map.replace(lg, rule); 
        return true;
    }

    /**
     * Получить колечество правил в таблице
     * @return
     */
    public int getSize(){
       return size;
    }

}

